package xyz.app.domain.parties;

import lombok.*;
import lombok.experimental.Accessors;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import xyz.app.Dao;
import xyz.app.DaoRegistry;
import xyz.app.MutableDomain;
import xyz.app.Wrapper;
import xyz.app.dependencies.HasDomainMembers;
import xyz.app.dependencies.HasOwners;
import xyz.app.dependencies.MemberAccessor;
import xyz.app.dependencies.OwnerEntry;
import xyz.app.domain.roles.*;

import java.util.*;

@Slf4j
@Service
@RequiredArgsConstructor(access = AccessLevel.PRIVATE)
public class DaoParty implements Dao<AbstractParty>,
        HasDomainMembers<AbstractParty>,
        HasOwners.HasRemovableOwners<AbstractParty>,
        MutableDomain {

    @Getter @Accessors(fluent = true)
    private final DaoRegistry daoRegistry;

    private final Collection<OwnerEntry<?, AbstractParty>> ownersMapping = new HashSet<>();

    @Getter @Accessors(fluent = true)
    private final Collection<MemberAccessor> memberAccessors = Set.of(
            MemberAccessor.of(AbstractParty_.BUSINESS_FORM,         Wrapper::businessForm,          Wrapper::businessForm),
            MemberAccessor.of(AbstractParty_.NAME,                  Wrapper::name,                  Wrapper::name),
            MemberAccessor.of(AbstractParty_.BUSINESS_REGISTRATION, Wrapper::businessRegistration,  Wrapper::businessRegistration),
            MemberAccessor.of(AbstractParty_.ADDRESS,               Wrapper::address,               Wrapper::address),
            MemberAccessor.of(AbstractParty_.LEGAL_ADDRESS,         Wrapper::legalAddress,          Wrapper::legalAddress));

    @Override
    public Collection<OwnerEntry<?, AbstractParty>> ownersMapping() {

        if (ownersMapping.isEmpty()) {
            daoRegistry.ownerEntry(Bank_.party, Bank.class).ifPresent(ownersMapping::add);
            daoRegistry.ownerEntry(Parent_.party, Parent.class).ifPresent(ownersMapping::add);
            daoRegistry.ownerEntryRemovable(Branch_.party, Branch.class).ifPresent(ownersMapping::add);
        }

        return ownersMapping;
    }

    @Override
    public @NonNull Class<AbstractParty> domainClass() {
        return AbstractParty.class;
    }
}